package com.xafc.demo.sys.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xafc.demo.sys.dao.MenuMapper;
import com.xafc.demo.sys.model.dto.MenuDTreeDto;
import com.xafc.demo.sys.model.dto.MenuDto;
import com.xafc.demo.sys.model.dto.MenuTreeDto;
import com.xafc.demo.sys.model.entity.Menu;
import com.xafc.demo.security.utils.CurrentUser;
import com.xafc.demo.framework.result.ResultCode;
import com.xafc.demo.sys.model.query.MenuPageQuery;
import com.xafc.demo.sys.service.IMenuService;
import com.xafc.demo.sys.service.IUserService;
import com.xafc.demo.framework.utils.CommonUtils;
import com.xafc.demo.security.utils.UserHolderUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Autowired
    private IUserService userService;

    @Override
    public Page<MenuDto> getMenuList(MenuPageQuery query) {
        final Page<MenuDto> page = new Page<>();
        List<MenuDto> menuList = baseMapper.selectMenuList();
        if (StrUtil.isEmpty(query.getSearch())){
            page.setRecords(menuList);
        }else {
            // 程序过滤
            List<MenuDto> resultList = new ArrayList<>();
            List<MenuDto>  parentMenuList = menuList.stream().filter(i -> i.getParent() == 0).collect(Collectors.toList());
            for (MenuDto parent : parentMenuList ) {
                if (parent.getName().equals(query.getSearch())){
                    resultList.add(parent);
                    menuListRecursiveHandle(parent, menuList, resultList);
                }
            }
            page.setRecords(resultList);
        }
        return page;
    }

    /**
     * 递归当前父菜单下的所有子菜单
     * @param parent 父菜单
     * @param menuList 菜单列表
     * @param resultList 结果就
     */
    private void menuListRecursiveHandle(MenuDto parent, List<MenuDto> menuList, List<MenuDto> resultList){
        Integer pid = parent.getId();
        for (MenuDto menu : menuList){
            if(menu.getParent().equals(pid)){
                resultList.add(menu);
                // 递归
                menuListRecursiveHandle(menu, menuList, resultList);
            }
        }
    }

    @Override
    public List<MenuTreeDto> getMenuTree() {
        // 获取所有角色中的所有权限
        CurrentUser currentUser = UserHolderUtils.getUser();
        List<MenuDto> menuDtoList = userService.getUserPerm(currentUser.getUserId());
        List<String> menuIdList = menuDtoList.stream().map(MenuDto::getId).map(Objects::toString).collect(Collectors.toList());

        // 根据用户的权限进行查询
        List<MenuTreeDto> menuList = baseMapper.selectMenuTree(String.join(",", menuIdList));
        menuList.forEach(i -> i.setHref(CommonUtils.getContextPath() + i.getHref()));

        List<MenuTreeDto> parentMenuList = menuList.stream()
                .filter(m -> m.getParent() == 0)
                .sorted(Comparator.comparingInt(MenuTreeDto::getSort))
                .collect(Collectors.toList());

        for (MenuTreeDto parent : parentMenuList){
            menuTreeRecursiveHandle(parent, menuList);
        }
        return parentMenuList;
    }

    /**
     * 递归处理菜单资源
     * @param parent 父级菜单
     * @param menuList 查询到的菜单资源
     */
    private void menuTreeRecursiveHandle(MenuTreeDto parent, List<MenuTreeDto> menuList){
        Integer pid = parent.getId();
        List<MenuTreeDto> children = new ArrayList<>();
        for (MenuTreeDto menu : menuList){
            if(menu.getParent().equals(pid)){
                children.add(menu);
                // 递归
                menuTreeRecursiveHandle(menu, menuList);
            }
        }
        parent.setChildren(children);
    }

    @Override
    public List<MenuDTreeDto> getMenuDTree() {
        //菜单列表需要获取当前登录的用户的角色，在获取所有角色中的权限，在进行以下的处理。
        List<MenuDTreeDto> menuList = baseMapper.selectMenuDTree();
        menuList.forEach(i -> i.setHref(CommonUtils.getContextPath() + i.getHref()));

        List<MenuDTreeDto> parentMenuList = menuList.stream()
                .filter(m -> m.getParentId() == 0)
                .sorted(Comparator.comparingInt(MenuDTreeDto::getSort))
                .collect(Collectors.toList());

        for (MenuDTreeDto parent : parentMenuList){
            menuDTreeRecursiveHandle(parent, menuList);
        }
        return parentMenuList;
    }

    /**
     * 递归处理菜单资源2
     * @param parent 父级菜单
     * @param menuList 查询到的菜单资源
     */
    private void menuDTreeRecursiveHandle(MenuDTreeDto parent, List<MenuDTreeDto> menuList){
        Integer pid = parent.getId();
        List<MenuDTreeDto> children = new ArrayList<>();
        for (MenuDTreeDto menu : menuList){
            if(menu.getParentId().equals(pid)){
                children.add(menu);
                // 递归
                menuDTreeRecursiveHandle(menu, menuList);
            }
        }
        parent.setChildren(children);
    }

    @Override
    public Menu getMenuById(Integer id) {
        return baseMapper.selectById(id);
    }

    @Override
    public Integer getCountByPid(Integer pid) {
        return baseMapper.selectCount(new QueryWrapper<Menu>().eq("parent", pid));
    }

    @Override
    public List<Menu> getMenuByIds(List<Integer> ids) {
//        return baseMapper.selectBatchIds(ids);
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.select("id", "href", "code").in("id", ids);
        return baseMapper.selectList(wrapper);
    }

    @Override
    public ResultCode addMenu(Menu menu) {
        ResultCode resultCode;
        Integer count = baseMapper.selectCount(new QueryWrapper<Menu>().eq("name", menu.getName()));
        if (count > 0){
            resultCode = ResultCode.fail("权限菜单已存在");
        }else {
            if(menu.getParent() == null) menu.setParent(0);  // 顶级菜单的parent必须为0, 不然前端展示有问题。
            if(menu.getSort() == null)  menu.setSort(0);
            menu.setCreateTime(new Date());
            menu.setCreator(UserHolderUtils.getUserId());

            int num= baseMapper.insert(menu);
            //新增成功
            if (num>0){
                resultCode = ResultCode.success("新增成功");
            }else {
                resultCode = ResultCode.error( "新增失败");
            }
        }
        return resultCode;
    }

    @Override
    public ResultCode updateMenu(Menu menu) {
        ResultCode resultCode;
        Integer count = baseMapper.selectCount(new QueryWrapper<Menu>().eq("id", menu.getId()));
        if(count > 0){
            menu.setUpdateTime(new Date());
            menu.setUpdater(UserHolderUtils.getUserId());
            int num = baseMapper.updateById(menu);
            if(num>0){
                resultCode = ResultCode.success("更新成功");
            }else {
                resultCode = ResultCode.error("更新失败");
            }
        }else {
            resultCode = ResultCode.fail("无效的权限菜单");
        }
        return resultCode;
    }

    @Override
    public ResultCode deleteMenu(Integer id) {
        ResultCode resultCode;
        Integer count = baseMapper.selectCount(new QueryWrapper<Menu>().eq("id", id));
        if(count > 0){
            int num = baseMapper.deleteById(id);
            if(num>0){
                resultCode = ResultCode.success("删除成功");
            }else {
                resultCode = ResultCode.error("删除失败");
            }
        }else {
            resultCode = ResultCode.fail("无效的权限菜单");
        }
        return resultCode;
    }
}
